package com.xique.park.service.biz.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xique.common.core.constant.HttpStatus;
import com.xique.common.core.utils.SecurityUtils;
import com.xique.common.core.utils.StringUtils;
import com.xique.common.core.web.domain.AjaxResult;
import com.xique.park.bean.domain.*;
import com.xique.park.bean.request.web.garageLaneDev.GarageLaneDevListRequest;
import com.xique.park.bean.request.web.garageLaneDev.GarageLaneDevNodeInfoRequest;
import com.xique.park.bean.request.web.garageLaneDev.board.BoardInfoRequest;
import com.xique.park.bean.request.web.garageLaneDev.board.LedSetRequest;
import com.xique.park.bean.request.web.garageLaneDev.board.VoiceSetRequest;
import com.xique.park.bean.request.web.garageLaneDev.board.VoiceTestRequest;
import com.xique.park.bean.request.web.garageLaneDev.garage.AddGarageRequest;
import com.xique.park.bean.request.web.garageLaneDev.garage.DeleteGarageRequest;
import com.xique.park.bean.request.web.garageLaneDev.garage.EditGarageRequest;
import com.xique.park.bean.request.web.garageLaneDev.ipc.AddIpcRequest;
import com.xique.park.bean.request.web.garageLaneDev.ipc.DeleteIpcRequest;
import com.xique.park.bean.request.web.garageLaneDev.ipc.EditIpcRequest;
import com.xique.park.bean.request.web.garageLaneDev.lane.AddLaneRequest;
import com.xique.park.bean.request.web.garageLaneDev.lane.DeleteLaneRequest;
import com.xique.park.bean.request.web.garageLaneDev.lane.EditLaneRequest;
import com.xique.park.bean.request.web.garageLaneDev.subdev.AddSubDevRequest;
import com.xique.park.bean.request.web.garageLaneDev.subdev.DeleteSubDevRequest;
import com.xique.park.bean.request.web.garageLaneDev.subdev.EditSubDevRequest;
import com.xique.park.bean.search.web.ParkGarageLaneDevListSearch;
import com.xique.park.bean.transform.web.garageLaneDev.*;
import com.xique.park.bean.vo.comm.GarageVo;
import com.xique.park.bean.vo.web.garageLaneDeviceTree.LedConfigVo;
import com.xique.park.bean.vo.web.garageLaneDeviceTree.TreeCommVo;
import com.xique.park.bean.vo.web.garageLaneDeviceTree.VoiceConfigVo;
import com.xique.park.constant.DictConstant;
import com.xique.park.constant.RedisConstants;
import com.xique.park.constant.message.LaneDtConstants;
import com.xique.park.controller.client.web.bean.search.ParkLaneCodeSearch;
import com.xique.park.enums.PayChannelEnum;
import com.xique.park.service.biz.service.IParkGarageLaneDevBizService;
import com.xique.park.service.command.service.IParkGarageCommandService;
import com.xique.park.service.command.service.IParkIpcCommandService;
import com.xique.park.service.command.service.IParkLaneCommandService;
import com.xique.park.service.service.*;
import com.xique.park.utils.RedisUtil;
import com.xique.park.utils.WechatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 车库通道设备serviceImpl
 *
 * @author xique
 */
@Service
public class ParkGarageLaneDevBizServiceImpl implements IParkGarageLaneDevBizService {

    @Value("${park.icbc.inParkUrl}")
    private String icbcInParkUrl;

    @Value("${park.icbc.outParkUrl}")
    private String icbcOutParkUrl;

    @Autowired
    private IParkGarageService parkGarageService;

    @Autowired
    private IParkLaneService parkLaneService;

    @Autowired
    private IParkDeviceNewService parkDeviceNewService;

    @Autowired
    private IParkDeviceSubService parkDeviceSubService;

    @Autowired
    private IParkCarMngtypeService parkCarMngtypeService;

    @Autowired
    private IParkGarageCommandService parkGarageCommandService;

    @Autowired
    private IParkLaneCommandService parkLaneCommandService;

    @Autowired
    private IParkIpcCommandService parkIpcCommandService;

    @Autowired
    private IParkLaneCodeService parkLaneCodeService;

    @Autowired
    private IParkPayPpService parkPayPpService;

    @Autowired
    private IParkCarMngtypeLaneService parkCarMngtypeLaneService;

    @Autowired
    private IParkCarMngtypeGarageService parkCarMngtypeGarageService;

    @Autowired
    private IParkInfoService parkInfoService;

    @Autowired
    private IParkChargeCarTempService chargeCarTempService;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private WechatUtils wechatUtils;

    @Value("${wx.park.mini.appid}")
    private String appId;

    @Value("${wx.park.mini.secret}")
    private String secret;


    /**
     * 获取树形列表
     */
    @Override
    public AjaxResult getTreeList(GarageLaneDevListRequest request) {
        ParkGarageLaneDevListSearch search = new ParkGarageLaneDevListSearch();
        search.setParkId(SecurityUtils.getParkId());
        Map<String, Object> map = new HashMap<>();
        ParkGarage parkGarage = new ParkGarage();
        parkGarage.setParkId(SecurityUtils.getParkId());
        // 1、查询车库通道设备
        List<Map<String, Object>> list = parkGarageService.getGarageLaneDevList(search);
        // 2、封装车库列表
        List<TreeCommVo> voList = ParkGarageLaneDeviceTransform.transformTreeGarageVo(list);
        // 3、封装通道设备
        Map<Long, List<TreeCommVo>> laneListMap = ParkGarageLaneDeviceTransform.transformTreeLaneVo(list);
        // 4、封装嵌套车库
        map.put("list", findTree(voList, laneListMap));
        return AjaxResult.success(map);
    }

    /**
     * 获取树节点信息
     */
    @Override
    public AjaxResult getNodeInfo(GarageLaneDevNodeInfoRequest request) {
        Object obj = null;
        Long id = request.getId();
        switch (request.getType()) {
            // 车库
            case "garage":
                ParkGarage parkGarage = parkGarageService.selectParkGarageById(id);
                ParkCarMngtype parkCarMngtype = new ParkCarMngtype();
                parkCarMngtype.setParkId(SecurityUtils.getParkId());
                List<ParkCarMngtype> mngtypeList = parkCarMngtypeService.selectParkCarMngtypeList(parkCarMngtype);
                obj = GarageTransform.transformNodeGarageVo(parkGarage, mngtypeList);
                break;
            // 通道
            case "lane":
                ParkLane parkLane = parkLaneService.selectParkLaneById(id);
                ParkGarage parkGarage1 = parkGarageService.selectParkGarageById(parkLane.getGarageId());
                obj = LaneTransform.transformNodeLaneVo(parkLane, parkGarage1);
                break;
            // 主相机
            case "ipc":
                ParkDeviceNew parkDeviceNew = parkDeviceNewService.selectParkDeviceNewById(id);
                ParkLane parkLane1 = parkLaneService.selectParkLaneById(parkDeviceNew.getLaneId());
                obj = IpcTransform.transformNodeIpcVo(parkDeviceNew, parkLane1);
                break;
            // 副相机
            case "ipc-sub":
                ParkDeviceNew parkDeviceIpcSub = parkDeviceNewService.selectParkDeviceNewById(id);
                ParkLane parkLane2 = parkLaneService.selectParkLaneById(parkDeviceIpcSub.getLaneId());
                obj = SubIpcTransform.transformNodeSubIpcVo(parkDeviceIpcSub, parkLane2);
                break;
            // ETC设备
            case "etc":
                ParkDeviceSub parkDeviceEtc = parkDeviceSubService.selectParkDeviceSubById(id);
                ParkLane parkLane3 = parkLaneService.selectParkLaneById(parkDeviceEtc.getLaneId());
                obj = SubDevTransform.transformNodeSubDevVo(parkDeviceEtc, parkLane3, "etc");
                break;
            // 扫描仪
            case "scanner":
                ParkDeviceSub parkDeviceScanner = parkDeviceSubService.selectParkDeviceSubById(id);
                ParkLane parkLane4 = parkLaneService.selectParkLaneById(parkDeviceScanner.getLaneId());
                obj = SubDevTransform.transformNodeSubDevVo(parkDeviceScanner, parkLane4, "scanner");
                break;
            // 剩余车位屏
            case "remain_display":
                ParkDeviceSub parkDeviceRemainDisplay = parkDeviceSubService.selectParkDeviceSubById(id);
                ParkLane parkLane5 = parkLaneService.selectParkLaneById(parkDeviceRemainDisplay.getLaneId());
                obj = SubDevTransform.transformNodeSubDevVo(parkDeviceRemainDisplay, parkLane5, "remain_display");
                break;
            default:
                break;
        }
        return AjaxResult.success(obj);
    }

    /* ------------------------------------- 车库相关方法 ------------------------------------- */

    @Override
    public AjaxResult getMngTypeList() {
        Map<String, Object> map = new HashMap<>();
        Long parkId = SecurityUtils.getParkId();
        if (null != parkId) {
            ParkCarMngtype parkCarMngtype = new ParkCarMngtype();
            parkCarMngtype.setParkId(parkId);
            List<ParkCarMngtype> mngtypeList = parkCarMngtypeService.selectParkCarMngtypeList(parkCarMngtype);
            map.put("list", GarageTransform.transformGarageMngTypeList(mngtypeList, new String[]{"0"}));
            return AjaxResult.success(map);
        } else {
            return AjaxResult.error("获取管理类型失败。车场参数不能为空");
        }
    }

    /**
     * 新增车库保存
     */
    @Override
    public AjaxResult addGarage(AddGarageRequest request) {
        // 判断车库名是否重复
        String name = request.getName();
        List<ParkGarage> parkGarageList = parkGarageService.selectParkGarageByName(name, SecurityUtils.getParkId());
        if (CollUtil.isNotEmpty(parkGarageList)) {
            return AjaxResult.error("保存失败，该车库名已存在");
        }
        ParkGarage parkGarage = GarageTransform.transformAddGarageRequest(request);
        int count = parkGarageService.insertParkGarage(parkGarage);
        if (count > 0) {
            AjaxResult result = parkGarageCommandService.downParkGarage(parkGarage, "保存成功！");
            result.put(AjaxResult.DATA_TAG, parkGarage);
            return result;
        } else {
            return AjaxResult.error("保存失败");
        }

    }

    /**
     * 编辑车库保存
     */
    @Override
    public AjaxResult editGarage(EditGarageRequest request) {
        ParkGarage oldParkGarage = parkGarageService.selectParkGarageById(request.getId());
        ParkGarage parkGarage = GarageTransform.transformEditGarageRequest(request);
        int count = parkGarageService.updateParkGarage(parkGarage);
        if (count > 0) {
            // 1、更新车库参数下发
            AjaxResult updateGarageResult = parkGarageCommandService.downParkGarage(parkGarage, "车库信息保存成功！");
            // 2、判断如果修改了车位总数、增减车位、参与车位统计的车辆管理类型，需要重新下发剩余车位数
            if (!StringUtils.equals(oldParkGarage.getTotalSpace().toString(), request.getTotalSpace().toString())
                    || !StringUtils.equals(oldParkGarage.getTempEmptySpace().toString(), request.getModifySpace().toString())
                    || !StringUtils.equals(oldParkGarage.getCountSpaceMngtype(), request.getSelectedMngTypeIds())) {
                AjaxResult updateSpacesResult = parkGarageCommandService.updateSpaces(parkGarage.getParkId(), parkGarage.getId());

                if (updateGarageResult.get(AjaxResult.CODE_TAG).equals(HttpStatus.COMMAND_ERROR)) {
                    return updateGarageResult;
                } else if (updateSpacesResult.get(AjaxResult.CODE_TAG).equals(HttpStatus.COMMAND_ERROR)) {
                    return AjaxResult.commandError("车库信息下发成功，剩余车位下发失败，请重新下发");
                } else {
                    return AjaxResult.success("车库信息下发成功，剩余车位下发成功");
                }
            }
            return updateGarageResult;
        } else {
            return AjaxResult.error("保存失败");
        }
    }

    /**
     * 删除车库
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public AjaxResult deleteGarage(DeleteGarageRequest request) {
        if (null == request.getId()) {
            return AjaxResult.error("删除车库失败，ID不能为空");
        }

        //1、删除车库和车辆管理权限的关系信息
        ParkCarMngtypeGarage parkCarMngtypeGarage = new ParkCarMngtypeGarage();
        parkCarMngtypeGarage.setParkId(request.getParkId());
        parkCarMngtypeGarage.setGarageId(request.getId());
        parkCarMngtypeGarageService.deleteParkCarMngtypeGarage(parkCarMngtypeGarage);


        //2、删除车库费率记录
        ParkChargeCarTemp parkChargeCarTemp = new ParkChargeCarTemp();
        parkChargeCarTemp.setParkId(request.getParkId());
        parkChargeCarTemp.setGarageId(request.getId());
        List<ParkChargeCarTemp> parkChargeCarTemps = chargeCarTempService.selectParkChargeCarTempList(parkChargeCarTemp);
        if (!parkChargeCarTemps.isEmpty()) {
            int i = chargeCarTempService.deleteParkChargeCarTempByIds(parkChargeCarTemps.stream().map(ParkChargeCarTemp::getId).collect(Collectors.toList()));
            if (i < 0) {
                return AjaxResult.error("删除失败");
            }
        }

        //3、删除车库
        int count = parkGarageService.deleteParkGarageById(request.getId());
        if (count < 0) {
            return AjaxResult.error("删除失败");
        }

        return parkGarageCommandService.delParkGarage(request.getId(), "车库删除成功！");
    }

    /* ------------------------------------- 通道相关方法 ------------------------------------- */

    /**
     * 新增通道保存
     */
    @Override
    public AjaxResult addLane(AddLaneRequest request) {
        ParkLane parkLane = LaneTransform.transformAddLaneRequest(request);

        if (DictConstant.LANE_TYPE_INSIDEIN.equals(request.getLaneType()) || DictConstant.LANE_TYPE_INSIDEOUT.equals(request.getLaneType())) {
            // 所属车库ID
            long garageId = parkLane.getGarageId();
            // 内场车库
            ParkGarage inParkGarage = parkGarageService.selectParkGarageById(garageId);
            // 获取外场车库
            if (null != inParkGarage) {
                parkLane.setOutGarageId(inParkGarage.getPid());
            }
        }

        int count = parkLaneService.insertParkLane(parkLane);
        if (count > 0) {
            parkLane.setLaneQrcode(laneQrCode(parkLane));
            AjaxResult result = parkLaneCommandService.downParkLane(parkLane, "通道保存成功！");
            result.put(AjaxResult.DATA_TAG, parkLane);
            return result;
        } else {
            return AjaxResult.error("保存失败");
        }
    }

    @Override
    public AjaxResult editLane(EditLaneRequest request) {
        ParkLane parkLane = LaneTransform.transformEditLaneRequest(request);

        if (DictConstant.LANE_TYPE_INSIDEIN.equals(request.getLaneType()) || DictConstant.LANE_TYPE_INSIDEOUT.equals(request.getLaneType())) {
            // 所属车库ID
            long garageId = parkLane.getGarageId();
            // 内场车库
            ParkGarage inParkGarage = parkGarageService.selectParkGarageById(garageId);
            // 获取外场车库
            if (null != inParkGarage) {
                parkLane.setOutGarageId(inParkGarage.getPid());
            }
        }

        int count = parkLaneService.updateParkLane(parkLane);
        if (count > 0) {
            parkLane.setLaneQrcode(laneQrCode(parkLane));
            return parkLaneCommandService.downParkLane(parkLane, "通道保存成功！");
        } else {
            return AjaxResult.error("保存失败");
        }
    }

    /**
     * 删除通道
     */
    @Override
    public AjaxResult deleteLane(DeleteLaneRequest request) {
        if (null != request.getId()) {
            int count = parkLaneService.deleteParkLaneById(request.getId());
            if (count > 0) {
                //删除当前通道设置的权限
                QueryWrapper<ParkCarMngtypeLane> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("park_id", SecurityUtils.getParkId());
                queryWrapper.eq("lane_id", request.getId());
                parkCarMngtypeLaneService.remove(queryWrapper);
                return AjaxResult.success("删除成功");
            } else {
                return AjaxResult.error("删除失败");
            }
        } else {
            return AjaxResult.error("删除通道失败。ID不能为空");
        }
    }

    @Override
    public AjaxResult getGarageList(ParkGarage parkGarage) {
        parkGarage.setParkId(SecurityUtils.getParkId());
        Map<String, Object> map = new HashMap<>(1);
        if (null != SecurityUtils.getParkId()) {
            List<ParkGarage> parkGarageList = parkGarageService.selectParkGarageList(SecurityUtils.getParkId(), parkGarage);
            List<GarageVo> voList = parkGarageList.stream().map(result -> {
                GarageVo vo = new GarageVo();
                vo.setGarageId(result.getId());
                vo.setGarageName(result.getName());
                return vo;
            }).collect(Collectors.toList());
            map.put("list", voList);
            return AjaxResult.success(map);
        } else {
            return AjaxResult.error("车库列表获取失败。车场参数不能为空");
        }
    }

    @Override
    public String laneQrCode(ParkLane parkLane) {
        if (null == parkLane || StringUtils.isEmpty(parkLane.getIsQrcode()) || DictConstant.NO.equals(parkLane.getIsQrcode())) {
            return "";
        }
        ParkLaneCode parkLaneCode = new ParkLaneCode();
        parkLaneCode.setType("pp");
        parkLaneCode.setStatus("normal");
        parkLaneCode.setParkId(parkLane.getParkId());
        parkLaneCode.setLaneId(parkLane.getId());
        List<ParkLaneCode> parkLaneCodeList = null != parkLane.getId() ? parkLaneCodeService.selectParkLaneCodeList(parkLaneCode) : new ArrayList<>();
        if (!CollectionUtils.isEmpty(parkLaneCodeList)) {
            return parkLaneCodeList.get(0).getUrl();
        }
        ParkPayPp parkPayPp = new ParkPayPp();
        parkPayPp.setParkId(parkLane.getParkId());
        parkPayPp.setStatus("normal");
        List<ParkPayPp> list = parkPayPpService.selectParkPayPpList(parkPayPp);
        if (CollectionUtils.isEmpty(list)) {
            return "";
        }
        ParkPayPp parkPayPp1 = list.get(0);
        String url;
        // 入场码
        if ("1".equals(parkLane.getLaneType())) {
            url = "https://qr.4pyun.com/parking?req=noplate&park_uuid=" + parkPayPp1.getParkUuid() + "&gate_id=" + parkLane.getId();
        } else {
            url = "https://qr.4pyun.com/parking?req=billing&park_uuid=" + parkPayPp1.getParkUuid() + "&gate_id=" + parkLane.getId();
        }
        parkLaneCode.setUrl(url);
        // 查询该通道支付二维码配置是否已经存在
        ParkLaneCodeSearch search = new ParkLaneCodeSearch();
        search.setLaneId(parkLaneCode.getLaneId());
        ParkLaneCodeV1 parkLaneCodeV1 = parkLaneCodeService.selectParkLaneCode(search);
        if (null == parkLaneCodeV1) {
            // 并将该二维码保存到数据库中
            parkLaneCodeService.insertParkLaneCode(parkLaneCode);
        } else {
            parkLaneCode.setId(parkLaneCodeV1.getId());
            parkLaneCodeService.updateParkLaneCode(parkLaneCode);
        }
        return url;
    }

    /* ------------------------------------- 主相机相关方法 ------------------------------------- */

    @Override
    public AjaxResult addIpc(AddIpcRequest request) {
        ParkDeviceNew parkDeviceNewInDb = parkDeviceNewService.selectParkDeviceNewByCode(request.getDevCode());
        if (null != parkDeviceNewInDb) {
            ParkInfo parkInfo = parkInfoService.selectParkInfoById(parkDeviceNewInDb.getParkId());
            return AjaxResult.error("该设备已被" + parkInfo.getName() + "车场添加！");
        }
        ParkDeviceNew parkDeviceNew = IpcTransform.transformAddIpcRequest(request);
        int count = parkDeviceNewService.insertParkDeviceNew(parkDeviceNew);
        if (count > 0) {
            AjaxResult result = mainIpcDownSubDevs(request.getDevCode(), request.getLaneId());
            result.put(AjaxResult.DATA_TAG, parkDeviceNew);
            return result;
        } else {
            return AjaxResult.error("保存失败");
        }
    }

    @Override
    public AjaxResult editIpc(EditIpcRequest request) {
        // 未修改之前数据库保存的设备信息
        ParkDeviceNew parkDeviceNewInDb = parkDeviceNewService.selectParkDeviceNewByCode(request.getDevCode());
        if (null != parkDeviceNewInDb && !parkDeviceNewInDb.getCode().equals(request.getDevCode())) {
            return AjaxResult.error("设备已被添加！");
        }
        ParkDeviceNew parkDeviceNew = IpcTransform.transformEditIpcRequest(request);
        int count = parkDeviceNewService.updateParkDeviceNew(parkDeviceNew);
        if (count > 0) {
            return mainIpcDownSubDevs(request.getDevCode(), request.getLaneId());
        } else {
            return AjaxResult.error("保存失败");
        }
    }

    /**
     * 主相机下发设备参数
     */
    private AjaxResult mainIpcDownSubDevs(String mainSn, Long laneId) {
        /* ------------------ UPDATE BY WLD 2022-04-29 START ------------------ */

        long parkId = SecurityUtils.getParkId();
        boolean result = Boolean.TRUE;

        // 根据通道ID获取通道信息
        ParkLane parkLane = parkLaneService.selectParkLaneById(laneId);
        if (null != parkLane) {
            // 根据车库ID获取车库信息
            ParkGarage parkGarage = parkGarageService.selectParkGarageById(parkLane.getGarageId());
            if (null != parkGarage) {
                // 下发车库信息
                AjaxResult garageResult = parkGarageCommandService.downParkGarage(parkGarage, "");
                if (garageResult.get(AjaxResult.CODE_TAG).equals(HttpStatus.COMMAND_ERROR)) {
                    result = false;
                }
            }

            // 下发通道信息
            AjaxResult laneResult = parkLaneCommandService.downParkLane(parkLane, "");
            if (laneResult.get(AjaxResult.CODE_TAG).equals(HttpStatus.COMMAND_ERROR)) {
                result = false;
            }
        }

        /* ------------------ UPDATE BY WLD 2022-04-29 END ------------------ */

        // 下发附加设备
        ParkDeviceSub parkDeviceSub = new ParkDeviceSub();
        parkDeviceSub.setParkId(parkId);
        parkDeviceSub.setLaneId(laneId);
        List<ParkDeviceSub> subDevList = parkDeviceSubService.selectParkDeviceSubList(parkDeviceSub);
        AjaxResult downSubDevsResult = parkIpcCommandService.downSubDevs(parkId, mainSn, subDevList, "");
        if (downSubDevsResult.get(AjaxResult.CODE_TAG).equals(HttpStatus.COMMAND_ERROR)) {
            result = false;
        }

        // 下发副摄像机
        ParkDeviceNew subIpc = new ParkDeviceNew();
        subIpc.setIsMain("N");
        subIpc.setParkId(parkId);
        subIpc.setLaneId(laneId);
        List<ParkDeviceNew> subIpcList = parkDeviceNewService.selectParkDeviceNewList(subIpc);
        AjaxResult downSubIpcResult = parkIpcCommandService.downSubIpc(parkId, mainSn, subIpcList, "");
        if (null != downSubIpcResult && downSubIpcResult.get(AjaxResult.CODE_TAG).equals(HttpStatus.COMMAND_ERROR)) {
            result = false;
        }

        if (result) {
            return AjaxResult.success("保存成功，下发成功");
        } else {
            return AjaxResult.commandError("保存成功，下发失败");
        }
    }

    @Override
    public AjaxResult deleteIpc(DeleteIpcRequest request) {
        ParkDeviceNew parkDeviceNew = parkDeviceNewService.selectParkDeviceNewById(request.getId());
        int count = parkDeviceNewService.deleteParkDeviceNewById(request.getId());
        if (count > 0) {
            // 清除缓存种的相机在线状态
            if (parkDeviceNew != null) {
                redisUtil.del(RedisConstants.REDIS_COMM_PREFIX + RedisConstants.REDIS_DEVICE_STATUS_PREFIX + parkDeviceNew.getCode());
            }
            return AjaxResult.success("删除成功");
        } else {
            return AjaxResult.error("删除失败");
        }
    }


    @Override
    public AjaxResult addSubDev(AddSubDevRequest request) {
        String subDevType = request.getType();
        if (StringUtils.isEmpty(subDevType)) {
            return AjaxResult.error("保存失败。设备类型不能为空");
        }
        /* 副相机保存处理 */
        if ("ipc-sub".equals(subDevType)) {
            if (StrUtil.isNotBlank(request.getDevCode())) {
                String pattern = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{8}$";
                Pattern r = Pattern.compile(pattern);
                Matcher m = r.matcher(request.getDevCode());
                if (!m.matches()) {
                    return AjaxResult.error("设备序列号不合规！");
                }
                ParkDeviceNew parkDeviceNewInDb = parkDeviceNewService.selectParkDeviceNewByCode(request.getDevCode());
                if (null != parkDeviceNewInDb) {
                    return AjaxResult.error("设备已被添加！");
                }
            }
            ParkDeviceNew parkDeviceNew = SubIpcTransform.transformAddSubIpcRequest(request);
            int count = parkDeviceNewService.insertParkDeviceNew(parkDeviceNew);
            if (count > 0) {
                List<ParkDeviceNew> subIpcList = new ArrayList<>(1);
                subIpcList.add(parkDeviceNew);
                AjaxResult result = parkIpcCommandService.downSubIpc(request.getLaneId(), subIpcList, "副相机保存成功！");
                result.put(AjaxResult.DATA_TAG, parkDeviceNew);
                return result;
            } else {
                return AjaxResult.error("保存失败");
            }
        } else {
            /* 其他附加设备保存处理 */
            ParkDeviceSub parkDeviceSub = SubDevTransform.transformAddSubDevRequest(request);
            int count = parkDeviceSubService.insertParkDeviceSub(parkDeviceSub);
            if (count > 0) {
                List<ParkDeviceSub> subDevList = new ArrayList<>(1);
                subDevList.add(parkDeviceSub);
                AjaxResult result = parkIpcCommandService.downSubDevs(request.getLaneId(), subDevList, "设备保存成功！");
                result.put(AjaxResult.DATA_TAG, parkDeviceSub);
                return result;
            } else {
                return AjaxResult.error("保存失败");
            }
        }
    }

    @Override
    public AjaxResult editSubDev(EditSubDevRequest request) {
        String subDevType = request.getType();
        if (StringUtils.isEmpty(subDevType)) {
            return AjaxResult.error("保存失败。设备类型不能为空");
        }
        /* 副相机保存处理 */
        if ("ipc-sub".equals(subDevType)) {
            if (StrUtil.isNotBlank(request.getDevCode())) {
                String pattern = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{8}$";
                Pattern r = Pattern.compile(pattern);
                Matcher m = r.matcher(request.getDevCode());
                if (!m.matches()) {
                    return AjaxResult.error("设备序列号不合规！");
                }
                ParkDeviceNew parkDeviceNewInDb = parkDeviceNewService.selectParkDeviceNewByCode(request.getDevCode());
                if (null != parkDeviceNewInDb && !parkDeviceNewInDb.getId().equals(request.getId())) {
                    return AjaxResult.error("设备已被添加！");
                }
            }
            ParkDeviceNew parkDeviceNew = SubIpcTransform.transformEditSubIpcRequest(request);
            int count = parkDeviceNewService.updateParkDeviceNew(parkDeviceNew);
            if (count > 0) {
                List<ParkDeviceNew> subIpcList = new ArrayList<>(1);
                subIpcList.add(parkDeviceNew);
                return parkIpcCommandService.downSubIpc(request.getLaneId(), subIpcList, "副相机保存成功！");
            } else {
                return AjaxResult.error("保存失败");
            }
        } else {
            ParkDeviceSub parkDeviceSub = SubDevTransform.transformEditSubDevRequest(request);
            int count = parkDeviceSubService.updateParkDeviceSub(parkDeviceSub);
            if (count > 0) {
                List<ParkDeviceSub> subDevList = new ArrayList<>(1);
                subDevList.add(parkDeviceSub);
                return parkIpcCommandService.downSubDevs(request.getLaneId(), subDevList, "设备保存成功！");
            } else {
                return AjaxResult.error("保存失败");
            }
        }
    }

    @Override
    public AjaxResult deleteSubDev(DeleteSubDevRequest request) {
        String subDevType = request.getType();
        if (StringUtils.isEmpty(subDevType)) {
            return AjaxResult.error("保存失败。设备类型不能为空");
        }
        /* 副相机删除处理 */
        if ("ipc-sub".equals(subDevType)) {
            int count = parkDeviceNewService.deleteParkDeviceNewById(request.getId());
            if (count > 0) {
                return parkIpcCommandService.delSubIpc(request.getLaneId(), request, "副相机删除成功！");
            } else {
                return AjaxResult.error("删除失败");
            }
        } else {
            /* 其他附加设备删除处理 */
            int count = parkDeviceSubService.deleteParkDeviceSubById(request.getId());
            if (count > 0) {
                return AjaxResult.success("删除成功");
            } else {
                return AjaxResult.error("删除失败");
            }
        }
    }

    @Override
    public AjaxResult getLedConfig(BoardInfoRequest request) {
        Long laneId = request.getLaneId();
        ParkLane parkLane = parkLaneService.selectParkLaneById(laneId);
        LedConfigVo ledConfigVo = BoardTransform.transformLedConfigVo(parkLane);
        return AjaxResult.success(ledConfigVo);
    }

    @Override
    public AjaxResult getVoiceConfig(BoardInfoRequest request) {
        Long laneId = request.getLaneId();
        ParkLane parkLane = parkLaneService.selectParkLaneById(laneId);
        VoiceConfigVo voiceConfigVo = BoardTransform.transformVoiceConfigVo(parkLane);
        return AjaxResult.success(voiceConfigVo);
    }

    @Override
    public AjaxResult setLed(LedSetRequest request) {
        ParkLane oldLane = parkLaneService.selectParkLaneById(request.getLaneId());
        ParkLane parkLane = BoardTransform.transformLedSetRequest(oldLane, request);
        int count = parkLaneService.updateParkLane(parkLane);
        if (count > 0) {
            return parkIpcCommandService.setLed(SecurityUtils.getParkId(), parkLane, "设置成功！");
        } else {
            return AjaxResult.error("设置失败");
        }
    }

    @Override
    public AjaxResult setVoice(VoiceSetRequest request) {
        ParkLane parkLane = BoardTransform.transformVoiceSetRequest(request);
        int count = parkLaneService.updateParkLane(parkLane);
        if (count > 0) {
            return parkIpcCommandService.setVoice(request.getLaneId(), request, "设置成功！");
        } else {
            return AjaxResult.error("设置失败");
        }
    }

    @Override
    public AjaxResult voiceTest(VoiceTestRequest request) {
        if (StringUtils.isNotEmpty(request.getDevCode())) {
            return parkIpcCommandService.voiceTest(request.getDevCode(), request);
        } else {
            if (null != request.getLaneId()) {
                return parkIpcCommandService.voiceTest(request.getLaneId(), request);
            } else {
                return AjaxResult.error("操作失败。设备序列号或者通道ID不能为空。");
            }
        }
    }

    @Override
    public AjaxResult generateQrcode(DeleteLaneRequest request) {
        Long parkId = SecurityUtils.getParkId();
        if (null == parkId) {
            return AjaxResult.error("车场ID不能为空");
        }
        ParkInfo info = parkInfoService.selectParkInfoById(parkId);
        if (ObjectUtil.isEmpty(info)) {
            return AjaxResult.error("未找到对应的车场信息");
        }
        ParkLane lane = parkLaneService.selectParkLaneById(request.getId());
        if (ObjectUtil.isEmpty(lane)) {
            return AjaxResult.error("未找到对应的通道信息");
        }
        Map<String, Object> map = new HashMap<>(1);
        if (PayChannelEnum.ICBC.getChannel().equals(info.getPayChannel())) {
            if ((LaneDtConstants.LANE_TYPE_IN.equals(request.getLaneType()) || LaneDtConstants.LANE_TYPE_BOTH.equals(request.getLaneType()))){
                map.put("url", "https://noplate.xiquepark.net?parkId="+ lane.getParkId() + "&laneId="+ lane.getId());
            }else if (LaneDtConstants.LANE_TYPE_OUT.equals(request.getLaneType())){
                map.put("url", "https://outpark.xiquepark.net?parkId="+ lane.getParkId() + "&laneId="+ lane.getId());
            }
            return AjaxResult.success(map);
        }
            ParkPayPp parkPayPp = new ParkPayPp();
            parkPayPp.setParkId(request.getParkId());
            List<ParkPayPp> list = parkPayPpService.selectParkPayPpList(parkPayPp);
            if (list.isEmpty()) {
                return AjaxResult.error("车场支付参数未配置");
            }
            if (list.size() > 1) {
                return AjaxResult.error("该车场存在多个电子支付配置，请联系管理人员");
            }
            String parkUuid = list.get(0).getParkUuid();
            if (StringUtils.isEmpty(parkUuid)) {
                return AjaxResult.error("UUID不能为空");
            }

            String inUrl = getInUrl(parkId);
            String outUrl = getOutUrl(parkId);
            String baseUrl = (request.getLaneType() == 1 || request.getLaneType() == 3) ? inUrl : outUrl;
            map.put("url", baseUrl + parkUuid + "&gate_id=" + request.getId());
        return AjaxResult.success(map);
    }

    private String getInUrl(Long parkId) {
        // 轻纺城面临采购中心
        if (590 == parkId) {
            return "https://qrx.4pyun.com/parking?req=noplate&park_uuid=";
        } else {
            return "https://qr.4pyun.com/parking?req=noplate&park_uuid=";
        }
    }

    private String getOutUrl(Long parkId) {
        // 轻纺城面临采购中心
        if (590 == parkId) {
            return "https://qrx.4pyun.com/parking?req=billing&park_uuid=";
        } else {
            return "https://qr.4pyun.com/parking?req=billing&park_uuid=";
        }
    }

    /* ------------------------------------- 以下为该类私有方法 ------------------------------------- */

    /**
     * 树形结构数据封装
     */
    private List<TreeCommVo> findTree(List<TreeCommVo> garageList, Map<Long, List<TreeCommVo>> laneListMap) {
        // 根节点
        List<TreeCommVo> rootGarage = new ArrayList<>();
        for (TreeCommVo garage : garageList) {
            if (null == garage.getPid() || 0 == garage.getPid()) {
                if (laneListMap.containsKey(garage.getId())) {
                    List<TreeCommVo> children = garage.getChildren();
                    if (!CollectionUtils.isEmpty(children)) {
                        children.addAll(laneListMap.get(garage.getId()));
                    }
                    garage.setChildren(laneListMap.get(garage.getId()));
                }
                rootGarage.add(garage);
            }
        }
        // 子车库
        for (TreeCommVo garage : rootGarage) {
            List<TreeCommVo> childList = getChild(garage.getId(), garageList, laneListMap);
            List<TreeCommVo> children = garage.getChildren();
            if (!CollectionUtils.isEmpty(children)) {
                children.addAll(childList);
            } else {
                children = childList;
            }
            garage.setChildren(children);
        }
        return rootGarage;
    }

    /**
     * 获取子列表
     */
    private List<TreeCommVo> getChild(Long id, List<TreeCommVo> garageList, Map<Long, List<TreeCommVo>> laneListMap) {
        // 子车库
        List<TreeCommVo> childList = new ArrayList<>();
        for (TreeCommVo garage : garageList) {
            if (null != garage.getPid() && id.equals(garage.getPid())) {
                if (laneListMap.containsKey(garage.getId())) {
                    List<TreeCommVo> children = garage.getChildren();
                    if (!CollectionUtils.isEmpty(children)) {
                        children.addAll(laneListMap.get(garage.getId()));
                    }
                    garage.setChildren(laneListMap.get(garage.getId()));
                }
                childList.add(garage);
            }
        }
        // 递归
        for (TreeCommVo garage : childList) {
            List<TreeCommVo> childList2 = getChild(garage.getId(), garageList, laneListMap);
            List<TreeCommVo> children = garage.getChildren();
            if (!CollectionUtils.isEmpty(children)) {
                children.addAll(childList2);
            } else {
                children = childList2;
            }
            garage.setChildren(children);
        }
        if (childList.size() == 0) {
            return new ArrayList<>();
        }
        return childList;
    }

    @Override
    public AjaxResult deleteDevices(Long parkId) {

        //删除主副相机
        ParkDeviceNew deviceNew = new ParkDeviceNew();
        deviceNew.setParkId(parkId);
        List<ParkDeviceNew> parkDeviceNews = parkDeviceNewService.selectParkDeviceNewList(deviceNew);
        if (!parkDeviceNews.isEmpty()) {
            parkDeviceNewService.deleteParkDeviceNewByIds(parkDeviceNews.stream().map(ParkDeviceNew::getId).collect(Collectors.toList()));
        }

        //删除附加设备
        ParkDeviceSub parkDeviceSub = new ParkDeviceSub();
        parkDeviceSub.setParkId(parkId);
        List<ParkDeviceSub> parkDeviceSubs = parkDeviceSubService.selectParkDeviceSubList(parkDeviceSub);
        if (parkDeviceSubs.isEmpty()) {
            return AjaxResult.success();
        }
        parkDeviceSubService.deleteParkDeviceSubByIds(parkDeviceSubs.stream().map(ParkDeviceSub::getId).collect(Collectors.toList()));

        return AjaxResult.success();
    }

}
